#ifndef KBASE_HPP_GUARD
#define KBASE_HPP_GUARD

#include "analogy.hpp"
#include "literal.hpp"
#include "rule.hpp"

#include "visitor.hpp"
#include "strategy.hpp"

namespace mashine { namespace kb {

// for resolving cross-class dependency 
namespace search { template<typename, typename > class SearchVisitor; }

/**
 * this method call to add new rule
 * if rule alredy exist it ignored.
 * 
 * rule - add-on rule
 */
class KnowledgeBase
{
public:
	/**
	 *
	 */
	KnowledgeBase();

	/**
	 *
	 */
	virtual ~KnowledgeBase();

	/**
	 * this method call to add new rule
	 * if rule alredy exist it ignored.
	 * 
	 * rule - add-on rule
	 */
	bool add(Rule rule) ;

	/**
	 * this method call to add new fact
	 * if fact alredy exist it ignored.
	 * 
	 * fact - add-on fact
	 */
	bool add(Literal fact) ;

	/**
	 * method call to add new analogy
	 * if analogy alredy exist it ignored.
	 * 
	 * analogy - add-on analogy
	 */
	bool add(Analogy analogy) ;

	/**
	 * return pointer to vector of pointers to rules
	 */
	std::vector<Rule> const & getRules() const;

	/**
	 * return pointer to vector of pointers to facts
	 */
	std::vector<Literal> const & getFacts() const;

	/**
	 * return pointer to vector of pointers to analogies
	 */
	std::vector<Analogy> const & getAnalogies() const;

	/**
	 * return current inference strategy
	 */
	mashine::inference::InferenceStrategy * getInferenceStrategy() const;

	/**
	 * set new inference strategy
	 *
	 * param strategy - pointer to new inference strategy
	 */
	void setInferenceStrategy(mashine::inference::InferenceStrategy * strategy);
	
	/**
	 * return result of search. after search visitor deleted
	 *
	 * param sVisitor - pointer to search visitor instance that realize
	 * search algorithm, paramethers search set by constructor of visitor
	 */
	template<typename _KbEntity, typename _Criteria>
	std::vector<_KbEntity> advanceSearch(search::SearchVisitor<_KbEntity, _Criteria> * sVisitor)
	{
		return sVisitor->search(this);
	}

	/**
	 * if request valide return 0 
	 * if invalid return first invalid request
	 * ref msg - result message
	 */
	int validateReques(std::vector<Literal> & target, std::string & msg);
	
	/**
	 * realization delegate to inference strategy method
	 *
	 * param goal - goal of search
	 *
	 * return vector results of search of empty vector 
	 */
	std::vector<Literal> inference(std::vector<Literal> const & goal) const;
	
private:

	mashine::inference::InferenceStrategy * strategy;
	
	std::vector<Rule> rules;
	std::vector<Literal> facts;
	std::vector<Analogy> analogies;
};

}}

#endif